package com.zmh.service.httpclient;

import java.io.IOException;
import java.net.SocketTimeoutException;

import org.apache.http.HttpHost;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.simple.SimpleLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;

/** 
 * @author zhoumh
 * @version 创建时间：2017年9月25日 下午5:01:41 
 * @Description 
*/
@Service
public class HttpConnectionManager {
	 /**
	  * 日志记录  
	  */
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnectionManager.class);  
    private static final String CHAR_SET = "UTF-8";  
  
  
    /** 
     * 最大连接数400 
     */  
    private static int MAX_CONNECTION_NUM = 500;  
  
  
    /** 
     * 单路由最大连接数80 
     */  
    private static int MAX_PER_ROUTE = 80;  
  
  
    /** 
     * 向服务端请求超时时间设置(单位:毫秒) 
     */  
    private static int SERVER_REQUEST_TIME_OUT = 10000;  
  
  
    /** 
     * 服务端响应超时时间设置(单位:毫秒) 
     */  
    private static int SERVER_RESPONSE_TIME_OUT = 10000;  
  
  
    /** 
     * 构造函数 
     */  
//    private HttpConnectionManager() {  
//    }  
  
  
    private static Object LOCAL_LOCK = new Object();  
      
    /** 
     * 连接池管理对象 
     */  
    PoolingHttpClientConnectionManager cm = null;  
  
  
    /** 
     *  
     * 功能描述: <br> 
     * 初始化连接池管理对象 
     * 
     * @see [相关类/方法](可选) 
     * @since [产品/模块版本](可选) 
     */  
    private PoolingHttpClientConnectionManager getPoolManager() {  
        final String methodName = "getPoolManager";  
//        LOGGER.info(methodName, "initPoolManager");  
        if (null == cm) {  
            synchronized (LOCAL_LOCK) {  
                if (null == cm) {  
                    SSLContextBuilder sslContextBuilder = new SSLContextBuilder();  
                    try {  
                        sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());  
                        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(  
                                sslContextBuilder.build());  
                        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()  
                                .register("https", socketFactory)  
                                .register("http", new PlainConnectionSocketFactory())  
                                .build();  
                        cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);  
                        cm.setMaxTotal(MAX_CONNECTION_NUM);  
                        cm.setDefaultMaxPerRoute(MAX_PER_ROUTE);  
                    } catch (Exception e) {  
                        LOGGER.info(methodName, "init PoolingHttpClientConnectionManager Error" + e);  
                    }  
  
  
                }  
            }  
        }  
//        LOGGER.info(methodName, "initPoolManager");  
        return cm;  
    }  
  
  
    /** 
     * 创建线程安全的HttpClient 
     *  
     * @return 
     */  
    public CloseableHttpClient getHttpsClient() {  
        final String methodName = "getHttpsClient";  
        HttpHost proxy = new HttpHost("localhost", 8888, "http"); 
        LOGGER.info(methodName, "initHttpsClient");  
        RequestConfig config = RequestConfig.custom()
				.setConnectionRequestTimeout(SERVER_RESPONSE_TIME_OUT)
				.setConnectTimeout(SERVER_REQUEST_TIME_OUT)
				.setCookieSpec(CookieSpecs.STANDARD_STRICT)
//				.setProxy(proxy) // 本地代理信息，用来fiddler拦截测试请求是否正确
				.build();
        CloseableHttpClient httpClient = HttpClients.custom()
        		.setDefaultRequestConfig(config)  
                .setConnectionManager(this.getPoolManager())  
                .build();  
//        LOGGER.info(methodName, "initHttpsClient");  
        return httpClient;  
    }  
  
  
    /** 
     * Https post请求 
     *  
     * @param url 请求地址 
     * @param json 请求参数(如果为null,则表示不请求参数) return 返回结果 
     */  
    public String poolHttpsPost(String url, JSONObject json) {  
        final String methodName = "poolHttpsPost";  
//        LOGGER.info(methodName, json);  
        CloseableHttpResponse response = null;  
        HttpPost post = null;  
        try {  
            // 设置代理  
//            HttpHost proxy = new HttpHost(InetAddressStr, InetPort);  
            // connectTimeout设置服务器请求超时时间  
            // socketTimeout设置服务器响应超时时间  
            RequestConfig requestConfig = RequestConfig.custom() 
                    .setSocketTimeout(SERVER_REQUEST_TIME_OUT).setConnectTimeout(SERVER_RESPONSE_TIME_OUT).build();  
            post = new HttpPost(url);  
            post.setConfig(requestConfig);  
  
  
            if (json != null) {  
                StringEntity se = new StringEntity(json.toString(), CHAR_SET);  
                se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;"));  
                post.setEntity(se);  
            }  
  
  
//            LOGGER.info(methodName, "start post to weixin");  
            response = getHttpsClient().execute(post);  
//            LOGGER.info(methodName, "end post to weixin");  
            int status = response.getStatusLine().getStatusCode();  
//            LOGGER.info(methodName, "return status:" + status);  
  
  
            String result = null;  
            if (status == 200) {  
                result = EntityUtils.toString(response.getEntity(), CHAR_SET);  
            }  
            EntityUtils.consume(response.getEntity());  
            response.close();  
//            LOGGER.info(methodName);  
            return result;  
        } catch (Exception e) {  
            if (e instanceof SocketTimeoutException) {  
                // 服务器请求超时  
//                LOGGER.error(methodName, "server request time out");  
            } else if (e instanceof ConnectTimeoutException) {  
                // 服务器响应超时(已经请求了)  
                LOGGER.error(methodName, "server response time out");  
            }  
            LOGGER.error(methodName, e.getMessage());  
        } finally {  
        	post.releaseConnection();  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                    response.close();  
                } catch (IOException e) {  
                    LOGGER.error(methodName, e.getMessage());  
                }  
            }  
        }  
//        LOGGER.info(methodName);  
        // 超时或者网络不通时返回值  
        return null;  
    }  
}
